from django import forms
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.db import IntegrityError
from .models import Student, StudyGoal, PastExamScore, TargetScore


class StudentForm(forms.ModelForm):
    """学生信息表单：包含登录账号字段，自动关联User"""
    # 登录账号字段（与User模型关联，创建时必填）
    student_username = forms.CharField(
        label="登录用户名",
        max_length=150,
        widget=forms.TextInput(
            attrs={
                'class': 'form-control',
                'placeholder': '如：zhangsan（仅字母、数字、下划线）',
                'required': 'required'
            }
        ),
        help_text="用于学生登录系统，不可重复，必填",
        required=True
    )
    student_password = forms.CharField(
        label="初始密码",
        widget=forms.PasswordInput(
            attrs={
                'class': 'form-control',
                'placeholder': '建议设置简单密码（如123456）',
                'required': 'required'
            }
        ),
        help_text="学生首次登录的密码，创建时必填；编辑时不填则保持原密码",
        required=False
    )

    class Meta:
        model = Student
        # 排除user字段（避免传递空值到模型），只包含学生自身字段
        fields = [
            'name', 'phone', 'email', 'attempt_count', 'education_background',
            'undergraduate_school', 'undergraduate_major', 'postgraduate_status',
            'target_school', 'target_major', 'target_code','exam_type',
            'has_politics', 'has_english', 'english_type',
            'has_math', 'math_type', 'professional_subject_name',
            'professional_subject_code', 'notes'
        ]
        widgets = {
            # 基础信息
            'name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '请输入学生真实姓名'}),
            'phone': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '11位手机号，可选'}),
            'email': forms.EmailInput(attrs={'class': 'form-control', 'placeholder': '如：student@xxx.com，可选'}),
            # 下拉选择框
            'attempt_count': forms.Select(attrs={'class': 'form-select'}),
            'education_background': forms.Select(attrs={'class': 'form-select'}),
            'postgraduate_status': forms.Select(attrs={'class': 'form-select'}),
            'english_type': forms.Select(attrs={'class': 'form-select'}),
            'math_type': forms.Select(attrs={'class': 'form-select'}),
            # 院校专业
            'undergraduate_school': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '如：XX大学'}),
            'undergraduate_major': forms.TextInput(
                attrs={'class': 'form-control', 'placeholder': '如：计算机科学与技术'}),
            'target_school': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '如：XX大学'}),
            'target_major': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '如：计算机科学与技术'}),
            'target_code': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '如：081200'}),
            'professional_subject_name': forms.TextInput(
                attrs={'class': 'form-control', 'placeholder': '如：计算机学科专业基础'}),
            'professional_subject_code': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '如：408'}),
            # 备注
            'notes': forms.Textarea(attrs={'class': 'form-control', 'rows': 3, 'placeholder': '可选，填写备注信息'}),
        }
        labels = {
            'name': '学生姓名 *',
            'phone': '手机号',
            'email': '邮箱',
            'attempt_count': '考研战数',
            'education_background': '学历背景',
            'postgraduate_status': '考研状态',
            'undergraduate_school': '本科院校',
            'undergraduate_major': '本科专业',
            'target_school': '目标院校',
            'target_major': '目标专业',
            'target_code': '专业代码',
            'has_politics': '是否考政治',
            'has_english': '是否考英语',
            'english_type': '英语类型',
            'has_math': '是否考数学',
            'math_type': '数学类型',
            'professional_subject_name': '专业课名称',
            'professional_subject_code': '专业课代码',
            'notes': '备注',
        }

    def __init__(self, *args, **kwargs):
        """初始化：处理request参数，区分创建/编辑场景"""
        self.request = kwargs.pop('request', None)
        super().__init__(*args, **kwargs)

        # 更准确的判断：只有实例有pk且有关联user才算是编辑模式
        is_editing = (self.instance and
                      self.instance.pk and
                      hasattr(self.instance, 'user') and
                      self.instance.user is not None)

        if is_editing:
            print(f"DEBUG: 初始化编辑表单，student_id={self.instance.pk}")

            # 设置用户名
            self.fields['student_username'].initial = self.instance.user.username
            # 用户名只读
            self.fields['student_username'].widget.attrs['readonly'] = 'readonly'
            self.fields['student_username'].required = False
            # 密码非必填
            self.fields['student_password'].required = False
            self.fields['student_password'].help_text = "编辑时不填则保持原密码"

        else:
            print("DEBUG: 初始化创建表单")
            self.fields['student_password'].required = True
            # 确保用户名字段可写
            self.fields['student_username'].widget.attrs.pop('readonly', None)

    def clean(self):
        """全局校验：处理英语/数学的关联选择"""
        cleaned_data = super().clean()

        # 1. 英语选择校验：勾选"考英语"则必须选择英语类型
        has_english = cleaned_data.get('has_english')
        english_type = cleaned_data.get('english_type')
        if has_english and english_type == '不考':
            self.add_error('english_type', '已勾选"考英语"，请选择英语类型（英语一/英语二）')
        elif not has_english and english_type != '不考':
            self.add_error('has_english', '已选择英语类型，需勾选"考英语"')

        # 2. 数学选择校验：勾选"考数学"则必须选择数学类型
        has_math = cleaned_data.get('has_math')
        math_type = cleaned_data.get('math_type')
        if has_math and math_type == '不考':
            self.add_error('math_type', '已勾选"考数学"，请选择数学类型（数学一/数学二/数学三）')
        elif not has_math and math_type != '不考':
            self.add_error('has_math', '已选择数学类型，需勾选"考数学"')

        # 3. 手机号格式校验（若填写）
        phone = cleaned_data.get('phone')
        if phone and phone.strip():
            phone = phone.strip()
            if not (len(phone) == 11 and phone.isdigit()):
                self.add_error('phone', '手机号必须是11位数字（如：13812345678）')
            cleaned_data['phone'] = phone

        return cleaned_data

    def clean_student_username(self):
        """用户名校验：创建时确保唯一，只允许字母、数字、下划线"""
        username = self.cleaned_data.get('student_username')
        if not username:
            raise forms.ValidationError("用户名不能为空")

        username = username.strip()
        # 只允许字母、数字、下划线
        if not username.replace('_', '').isalnum():
            raise forms.ValidationError("用户名仅支持字母、数字和下划线，不允许特殊字符")

        # 编辑场景：不校验唯一性（用户名只读，不会修改）
        if self.instance and self.instance.pk:
            return username

        # 创建场景：检查用户名是否被活跃的学生占用
        # 这里检查的是 Student 表中是否存在关联这个用户名的记录
        if Student.objects.filter(user__username=username).exists():
            raise forms.ValidationError(f"用户名「{username}」已被占用，请更换其他用户名")

        return username

    def save(self, commit=True):
        """保存逻辑：创建时调用模型方法关联User，编辑时更新基础信息"""

        # 更准确的判断：只有实例有pk且有关联user才算是编辑模式
        is_editing = (self.instance and
                      self.instance.pk and
                      hasattr(self.instance, 'user') and
                      self.instance.user is not None)

        # 1. 创建新学生
        if not is_editing:
            username = self.cleaned_data.get('student_username')
            password = self.cleaned_data.get('student_password')

            if not username:
                raise ValidationError("创建学生必须提供用户名")
            if not password:
                raise ValidationError("创建学生必须提供初始密码")

            # 整理学生信息
            student_data = {
                field: self.cleaned_data.get(field)
                for field in self.Meta.fields
                if field in self.cleaned_data
            }

            print(f"DEBUG: 创建新学生，username={username}")

            try:
                # 调用模型方法创建
                self.instance = Student.create_with_user(
                    username=username,
                    password=password,
                    **student_data
                )
                print(f"DEBUG: 学生创建完成，student_id={self.instance.id}")

            except ValidationError as e:
                print(f"DEBUG: ValidationError: {str(e)}")
                raise e
            except Exception as e:
                print(f"DEBUG: 创建学生异常: {str(e)}")
                raise ValidationError(f"创建学生失败：{str(e)}")

        # 2. 编辑学生
        else:
            print(f"DEBUG: 编辑学生，student_id={self.instance.id}")

            # 更新学生自身字段
            for field in self.Meta.fields:
                if field in self.cleaned_data and self.cleaned_data[field] is not None:
                    setattr(self.instance, field, self.cleaned_data[field])

            # 处理密码更新
            new_password = self.cleaned_data.get('student_password')
            if new_password and new_password.strip():
                if len(new_password.strip()) < 6:
                    raise ValidationError("密码长度不能少于6位")

                self.instance.user.set_password(new_password.strip())
                self.instance.user.save()
                print(f"DEBUG: 密码已更新")

            # 保存Student信息
            if commit:
                try:
                    self.instance.save()
                    print(f"DEBUG: 学生信息保存成功")
                except Exception as e:
                    print(f"DEBUG: 保存失败: {str(e)}")
                    raise ValidationError(f"保存失败：{str(e)}")

        return self.instance

class PastExamScoreForm(forms.ModelForm):
    """往年考试成绩表单（动态显示学生实际考试科目）"""

    class Meta:
        model = PastExamScore
        fields = ['exam_year', 'total_score', 'politics_score',
                  'english_score', 'math_score', 'professional_score', 'notes']
        widgets = {
            'exam_year': forms.NumberInput(attrs={
                'class': 'form-control',
                'min': '2000',
                'max': '2030',
                'placeholder': '如：2024'
            }),
            'total_score': forms.NumberInput(attrs={
                'class': 'form-control',
                'step': '0.5',
                'min': '0',
                'max': '500',
                'placeholder': '总分（0-500）'
            }),
            'politics_score': forms.NumberInput(attrs={
                'class': 'form-control',
                'step': '0.5',
                'min': '0',
                'max': '100',
                'placeholder': '政治分数（0-100）'
            }),
            'english_score': forms.NumberInput(attrs={
                'class': 'form-control',
                'step': '0.5',
                'min': '0',
                'max': '100',
                'placeholder': '英语分数（0-100）'
            }),
            'math_score': forms.NumberInput(attrs={
                'class': 'form-control',
                'step': '0.5',
                'min': '0',
                'max': '150',
                'placeholder': '数学分数（0-150）'
            }),
            'professional_score': forms.NumberInput(attrs={
                'class': 'form-control',
                'step': '0.5',
                'min': '0',
                'max': '150',
                'placeholder': '专业课分数（0-150）'
            }),
            'notes': forms.Textarea(attrs={
                'class': 'form-control',
                'rows': 3,
                'placeholder': '可选，填写成绩备注（如：第一次参加考试）'
            }),
        }
        labels = {
            'exam_year': '考试年份',
            'total_score': '总分',
            'politics_score': '政治分数',
            'english_score': '英语分数',
            'math_score': '数学分数',
            'professional_score': '专业课分数',
            'notes': '备注'
        }

    def __init__(self, *args, **kwargs):
        """初始化：根据学生考试科目动态设置字段"""
        self.student = kwargs.pop('student', None)
        super().__init__(*args, **kwargs)

        if self.student:
            self.setup_dynamic_fields()

    def setup_dynamic_fields(self):
        """根据学生配置动态设置科目字段"""
        # 政治科目
        if not self.student.has_politics:
            self.fields['politics_score'].widget = forms.HiddenInput()
            self.fields['politics_score'].required = False
            self.fields['politics_score'].label = ''

        # 英语科目
        if not self.student.has_english:
            self.fields['english_score'].widget = forms.HiddenInput()
            self.fields['english_score'].required = False
            self.fields['english_score'].label = ''
        else:
            # 更新英语科目标签显示具体类型
            english_type = self.student.english_type
            if english_type != '不考':
                self.fields['english_score'].label = f'{english_type}分数'

        # 数学科目
        if not self.student.has_math:
            self.fields['math_score'].widget = forms.HiddenInput()
            self.fields['math_score'].required = False
            self.fields['math_score'].label = ''
        else:
            # 更新数学科目标签显示具体类型
            math_type = self.student.math_type
            if math_type != '不考':
                self.fields['math_score'].label = f'{math_type}分数'

        # 专业课科目
        if not self.student.professional_subject_name:
            self.fields['professional_score'].widget = forms.HiddenInput()
            self.fields['professional_score'].required = False
            self.fields['professional_score'].label = ''
        else:
            # 更新专业课标签显示具体名称
            subject_name = self.student.professional_subject_name
            self.fields['professional_score'].label = f'{subject_name}分数'

    def get_visible_subjects(self):
        """获取需要显示的成绩科目"""
        subjects = []
        if self.student:
            if self.student.has_politics:
                subjects.append({
                    'field': 'politics_score',
                    'name': '政治',
                    'icon': 'vote-yea',
                    'color_class': 'politics-icon',
                    'max_score': 100
                })
            if self.student.has_english:
                english_type = self.student.english_type
                display_name = english_type if english_type != '不考' else '英语'
                subjects.append({
                    'field': 'english_score',
                    'name': display_name,
                    'icon': 'language',
                    'color_class': 'english-icon',
                    'max_score': 100
                })
            if self.student.has_math:
                math_type = self.student.math_type
                display_name = math_type if math_type != '不考' else '数学'
                subjects.append({
                    'field': 'math_score',
                    'name': display_name,
                    'icon': 'calculator',
                    'color_class': 'math-icon',
                    'max_score': 150
                })
            if self.student.professional_subject_name:
                subjects.append({
                    'field': 'professional_score',
                    'name': self.student.professional_subject_name,
                    'icon': 'book',
                    'color_class': 'professional-icon',
                    'max_score': 150
                })
        return subjects

    def clean(self):
        cleaned_data = super().clean()
        # 1. 校验考试年份（范围：2000-当前年份+1，避免未来过多年份）
        from datetime import datetime
        current_year = datetime.now().year
        exam_year = cleaned_data.get('exam_year')
        if exam_year:
            if exam_year < 2000 or exam_year > current_year + 1:
                self.add_error('exam_year', f'考试年份需在2000-{current_year + 1}之间')

        # 2. 动态校验各科目分数（根据学生实际考试科目）
        if self.student:
            if self.student.has_politics:
                politics = cleaned_data.get('politics_score')
                if politics is not None and (politics < 0 or politics > 100):
                    self.add_error('politics_score', '政治分数需在0-100之间')

            if self.student.has_english:
                english = cleaned_data.get('english_score')
                if english is not None and (english < 0 or english > 100):
                    self.add_error('english_score', '英语分数需在0-100之间')

            if self.student.has_math:
                math = cleaned_data.get('math_score')
                if math is not None and (math < 0 or math > 150):
                    self.add_error('math_score', '数学分数需在0-150之间')

            if self.student.professional_subject_name:
                professional = cleaned_data.get('professional_score')
                if professional is not None and (professional < 0 or professional > 150):
                    self.add_error('professional_score', '专业课分数需在0-150之间')

        # 3. 校验总分与各科目分数之和（允许0.1的浮点误差）
        total = cleaned_data.get('total_score')
        if total is not None:
            sum_score = 0
            # 只累加学生实际考试的科目
            if self.student:
                if self.student.has_politics:
                    politics = cleaned_data.get('politics_score')
                    if politics is not None:
                        sum_score += politics
                if self.student.has_english:
                    english = cleaned_data.get('english_score')
                    if english is not None:
                        sum_score += english
                if self.student.has_math:
                    math = cleaned_data.get('math_score')
                    if math is not None:
                        sum_score += math
                if self.student.professional_subject_name:
                    professional = cleaned_data.get('professional_score')
                    if professional is not None:
                        sum_score += professional

            # 仅当有科目分数时才校验总分
            if sum_score > 0 and abs(total - sum_score) > 0.1:
                self.add_error('total_score', f'总分与各科目分数之和不符（实际应为：{sum_score:.1f}）')

        return cleaned_data

    def clean_exam_year(self):
        """单独校验考试年份非空"""
        exam_year = self.cleaned_data.get('exam_year')
        if not exam_year:
            raise forms.ValidationError("考试年份不能为空")
        return exam_year

    def clean_total_score(self):
        """单独校验总分非空"""
        total_score = self.cleaned_data.get('total_score')
        if total_score is None:
            raise forms.ValidationError("总分不能为空")
        return total_score

class StudyGoalForm(forms.ModelForm):
    """学习目标表单（补充标签、默认值和校验）"""
    # 补充：优先级默认值为3（中等优先级），并限制范围
    priority = forms.IntegerField(
        label="优先级",
        min_value=1,
        max_value=5,
        initial=3,
        widget=forms.NumberInput(attrs={
            'class': 'form-control',
            'min': '1',
            'max': '5',
            'placeholder': '1=最低，5=最高'
        }),
        help_text="1=最低优先级，5=最高优先级（用于排序学习任务）"
    )

    def __init__(self, *args, **kwargs):
        student = kwargs.pop('student', None)
        super().__init__(*args, **kwargs)

        # 1. 动态设置科目选择（基于学生已选考试科目）
        subject_choices = []
        if student:
            # 政治：勾选“考政治”则加入选项
            if student.has_politics:
                subject_choices.append(('政治', '政治'))
            # 英语：勾选“考英语”且类型不是“不考”则加入选项
            if student.has_english and student.english_type != '不考':
                subject_choices.append((student.english_type, student.english_type))
            # 数学：勾选“考数学”且类型不是“不考”则加入选项
            if student.has_math and student.math_type != '不考':
                subject_choices.append((student.math_type, student.math_type))
            # 专业课：填写了专业课名称则加入选项
            if student.professional_subject_name:
                subject_choices.append(('专业课', student.professional_subject_name))  # 显示具体专业课名称

        # 若没有可选科目，添加提示选项并禁用选择
        if not subject_choices:
            subject_choices.append(('无', '该学生未设置考试科目，请先完善学生信息'))
            self.fields['subject_type'].widget.attrs['disabled'] = True
        self.fields['subject_type'].choices = subject_choices

        # 2. 补充所有字段的中文标签和样式优化
        self.fields['subject_type'].label = "科目类型"
        self.fields['subject_type'].widget.attrs['class'] = 'form-select'

        self.fields['target_score'].label = "目标分数"
        self.fields['target_score'].widget = forms.NumberInput(attrs={
            'class': 'form-control',
            'step': '0.5',
            'min': '0',
            'max': '150',
            'placeholder': '根据科目满分设置（如：政治100/数学150）'
        })

        self.fields['current_level'].label = "当前水平"
        self.fields['current_level'].widget.attrs['class'] = 'form-select'

        self.fields['deadline'].label = "截止日期"
        self.fields['deadline'].widget.attrs.update({
            'class': 'form-control',
            'type': 'date'
        })

    class Meta:
        model = StudyGoal
        fields = ['subject_type', 'target_score', 'current_level', 'priority', 'deadline']
        # 模型中已定义的 choices 字段，补充默认标签
        labels = {
            'current_level': '当前水平'
        }

    def clean(self):
        cleaned_data = super().clean()
        # 1. 校验目标分数（不超过150，且为正数）
        target_score = cleaned_data.get('target_score')
        if target_score is not None:
            if target_score < 0 or target_score > 150:
                self.add_error('target_score', '目标分数需在0-150之间')

        # 2. 校验截止日期（不能早于当前日期）
        from datetime import date
        today = date.today()
        deadline = cleaned_data.get('deadline')
        if deadline and deadline < today:
            self.add_error('deadline', '截止日期不能早于当前日期，请选择未来日期')

        # 3. 校验科目类型（若学生未设置科目，禁止提交）
        subject_type = cleaned_data.get('subject_type')
        if subject_type == '无':
            self.add_error('subject_type', '无法创建学习目标：该学生未设置考试科目，请先完善学生信息')

        return cleaned_data

    def clean_target_score(self):
        """单独校验目标分数非空"""
        # 修复：添加 self 参数，并通过 self.cleaned_data 获取数据
        target_score = self.cleaned_data.get('target_score')
        if target_score is None:
            raise forms.ValidationError("目标分数不能为空")
        return target_score

    def clean_deadline(self):
        """单独校验截止日期非空"""
        # 修复：添加 self 参数，并通过 self.cleaned_data 获取数据
        deadline = self.cleaned_data.get('deadline')
        if not deadline:
            raise forms.ValidationError("截止日期不能为空")
        return deadline

class TargetScoreForm(forms.ModelForm):
    """目标成绩表单 - 动态显示学生实际考试科目"""

    class Meta:
        model = TargetScore
        exclude = ['student', 'display_name', 'region_adjustment', 'mock_score_trend']  # 排除自动生成的字段
        widgets = {
            'subject_category': forms.Select(attrs={
                'class': 'form-control',
                'id': 'subject-category-select'
            }),
            'ideal_target': forms.NumberInput(attrs={
                'class': 'form-control score-input',
                'step': '0.5',
                'min': '0',
                'placeholder': '理想目标分数'
            }),
            'realistic_target': forms.NumberInput(attrs={
                'class': 'form-control score-input',
                'step': '0.5',
                'min': '0',
                'placeholder': '实际目标分数'
            }),
            'safety_target': forms.NumberInput(attrs={
                'class': 'form-control score-input',
                'step': '0.5',
                'min': '0',
                'placeholder': '保底分数'
            }),
            'current_level': forms.NumberInput(attrs={
                'class': 'form-control score-input',
                'step': '0.5',
                'min': '0',
                'placeholder': '当前水平分数'
            }),
            'base_difficulty': forms.Select(attrs={
                'class': 'form-control difficulty-select'
            }),
            'goal_difficulty': forms.Select(attrs={
                'class': 'form-control difficulty-select'
            }),
            'confidence_level': forms.NumberInput(attrs={
                'class': 'form-control',
                'min': '0',
                'max': '100',
                'placeholder': '0-100'
            }),
            'study_phase': forms.Select(attrs={
                'class': 'form-control phase-select'
            }),
            'key_weak_points': forms.Textarea(attrs={
                'class': 'form-control',
                'rows': 3,
                'placeholder': '描述需要重点突破的知识点或题型...'
            }),
            'key_strengths': forms.Textarea(attrs={
                'class': 'form-control',
                'rows': 3,
                'placeholder': '描述已掌握较好的部分...'
            }),
            'study_strategy': forms.Textarea(attrs={
                'class': 'form-control',
                'rows': 4,
                'placeholder': '描述具体的学习方法和计划安排...'
            }),
            'primary_materials': forms.Textarea(attrs={
                'class': 'form-control',
                'rows': 3,
                'placeholder': '使用的教材、网课、习题集等...'
            }),
            'weekly_hours': forms.NumberInput(attrs={
                'class': 'form-control',
                'min': '0',
                'max': '40',
                'placeholder': '每周学习小时数'
            }),
            'overall_progress': forms.NumberInput(attrs={
                'class': 'form-control',
                'min': '0',
                'max': '100',
                'placeholder': '0-100'
            }),
            'last_mock_score': forms.NumberInput(attrs={
                'class': 'form-control score-input',
                'step': '0.5',
                'min': '0',
                'placeholder': '最近模拟成绩'
            }),
            'study_start_date': forms.DateInput(attrs={
                'class': 'form-control',
                'type': 'date'
            }),
            'target_completion_date': forms.DateInput(attrs={
                'class': 'form-control',
                'type': 'date'
            }),
            'priority': forms.NumberInput(attrs={
                'class': 'form-control',
                'min': '1',
                'max': '5',
                'placeholder': '1-5'
            }),
            'notes': forms.Textarea(attrs={
                'class': 'form-control',
                'rows': 4,
                'placeholder': '其他备注信息...'
            }),
        }
        labels = {
            'subject_category': '科目类别',
            'ideal_target': '理想目标分数',
            'realistic_target': '实际目标分数',
            'safety_target': '保底分数',
            'current_level': '当前水平分数',
            'base_difficulty': '基础水平',
            'goal_difficulty': '目标难度',
            'confidence_level': '达成信心(%)',
            'study_phase': '学习阶段',
            'key_weak_points': '重点薄弱环节',
            'key_strengths': '优势项目',
            'study_strategy': '学习策略',
            'primary_materials': '主要学习资料',
            'weekly_hours': '每周学习时长(小时)',
            'overall_progress': '整体进度(%)',
            'last_mock_score': '最近模拟成绩',
            'study_start_date': '开始复习日期',
            'target_completion_date': '目标完成日期',
            'priority': '备考优先级',
            'notes': '备注信息'
        }

    def __init__(self, *args, **kwargs):
        """初始化：根据学生考试科目动态设置科目选择"""
        self.student = kwargs.pop('student', None)
        super().__init__(*args, **kwargs)

        if self.student:
            self.setup_dynamic_fields()
        else:
            # 如果没有传入student，禁用科目选择
            self.fields['subject_category'].choices = []

    def setup_dynamic_fields(self):
        """根据学生配置动态设置科目字段"""
        # 过滤科目类别，只显示学生实际考试的科目
        available_categories = []

        if self.student.has_politics:
            available_categories.append(('politics', '政治'))
        if self.student.has_english:
            english_display = self.student.english_type if self.student.english_type != '不考' else '英语'
            available_categories.append(('english', english_display))
        if self.student.has_math:
            math_display = self.student.math_type if self.student.math_type != '不考' else '数学'
            available_categories.append(('math', math_display))
        if self.student.professional_subject_name:
            available_categories.append(('professional_1', self.student.professional_subject_name))
        if self.student.has_professional_2 and self.student.professional_subject_2_name:
            available_categories.append(('professional_2', self.student.professional_subject_2_name))

        self.fields['subject_category'].choices = available_categories

        # 设置科目类别的初始值（如果是编辑模式且科目无效，则清除）
        if self.instance and self.instance.pk:
            current_category = self.instance.subject_category
            valid_categories = [cat[0] for cat in available_categories]
            if current_category not in valid_categories:
                self.instance.subject_category = None

    def save(self, commit=True):
        """保存表单数据，确保student字段被正确设置"""
        instance = super().save(commit=False)

        # 关键修复：确保student字段被设置
        if self.student:
            instance.student = self.student

            # 自动设置显示名称
            instance.set_display_name()

            # 自动计算地域影响
            instance.calculate_region_adjustment()

        if commit:
            try:
                instance.save()
                print(
                    f"DEBUG: 保存成功，display_name: {instance.display_name}, region_adjustment: {instance.region_adjustment}")
            except Exception as e:
                print(f"DEBUG: 保存TargetScore时出错: {str(e)}")
                raise

        return instance

    def clean(self):
        """表单验证"""
        cleaned_data = super().clean()

        # 验证student是否存在
        if not self.student:
            raise forms.ValidationError("无法确定关联的学生信息")

        # 获取科目类别和对应的最大分数
        subject_category = cleaned_data.get('subject_category')
        if not subject_category:
            self.add_error('subject_category', '请选择科目类别')
            return cleaned_data

        max_scores = {
            'politics': 100,
            'english': 100,
            'math': 150,
            'professional_1': 150,
            'professional_2': 150,
        }
        max_score = max_scores.get(subject_category, 150)

        # 验证分数范围 - 添加 None 值检查
        ideal_target = cleaned_data.get('ideal_target')
        realistic_target = cleaned_data.get('realistic_target')
        safety_target = cleaned_data.get('safety_target')
        current_level = cleaned_data.get('current_level')
        last_mock_score = cleaned_data.get('last_mock_score')

        # 设置默认值
        if ideal_target is None:
            ideal_target = 0
        if realistic_target is None:
            realistic_target = 0
        if safety_target is None:
            safety_target = 0
        if current_level is None:
            current_level = 0

        if ideal_target > max_score:
            self.add_error('ideal_target', f'理想目标分数不能超过{max_score}分')
        if realistic_target > max_score:
            self.add_error('realistic_target', f'实际目标分数不能超过{max_score}分')
        if safety_target > max_score:
            self.add_error('safety_target', f'保底分数不能超过{max_score}分')
        if current_level > max_score:
            self.add_error('current_level', f'当前水平分数不能超过{max_score}分')
        if last_mock_score is not None and last_mock_score > max_score:
            self.add_error('last_mock_score', f'模拟成绩不能超过{max_score}分')

        # 验证分数逻辑
        if ideal_target < realistic_target:
            self.add_error('ideal_target', '理想目标应不低于实际目标')
        if realistic_target < safety_target:
            self.add_error('realistic_target', '实际目标应不低于保底分数')

        # 验证进度
        overall_progress = cleaned_data.get('overall_progress')
        if overall_progress is not None and (overall_progress < 0 or overall_progress > 100):
            self.add_error('overall_progress', '整体进度应在0-100之间')

        # 验证信心指数
        confidence_level = cleaned_data.get('confidence_level')
        if confidence_level is not None and (confidence_level < 0 or confidence_level > 100):
            self.add_error('confidence_level', '达成信心应在0-100之间')

        # 验证科目有效性
        if subject_category and self.student:
            # 检查科目是否与学生配置匹配
            if subject_category == 'politics' and not self.student.has_politics:
                self.add_error('subject_category', '该学生不考政治科目')
            elif subject_category == 'english' and not self.student.has_english:
                self.add_error('subject_category', '该学生不考英语科目')
            elif subject_category == 'math' and not self.student.has_math:
                self.add_error('subject_category', '该学生不考数学科目')
            elif subject_category == 'professional_1' and not self.student.professional_subject_name:
                self.add_error('subject_category', '该学生未设置专业课一')
            elif subject_category == 'professional_2' and not (
                    self.student.has_professional_2 and self.student.professional_subject_2_name):
                self.add_error('subject_category', '该学生未设置专业课二')

        return cleaned_data